#!/usr/bin/python
###############################################################################
#Programmers: Trebol-a, info@trebol-a.com                                     #
#             Danil Dotsenko, dd@accentsolution.com                           #
#Date: 20/07/2006                                                             #
#Filename: afoto.py                                                           #
#Version: 1.5b7                                                               #
#                                                                             #
#                                                                             #
#       Copyleft 2005 Alberto Garcia                                          #
#                                                                             #
#    This program is free software; you can redistribute it and/or modify     #
#    it under the terms of the GNU General Public License as published by     #
#    the Free Software Foundation; either version 2 of the License, or        #
#    (at your option) any later version.                                      #
#                                                                             #
#    This program is distributed in the hope that it will be useful,          #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
#    GNU General Public License for more details.                             #
#                                                                             #
#    You should have received a copy of the GNU General Public License        #
#    along with this program; if not, write to the Free Software              #
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA #
#                                                                             #
###############################################################################

from __future__ import division
import karamba
import os 
import commands 
import random
import glob
import re
from zipfile import is_zipfile
from StringIO import StringIO
from gettext import GNUTranslations
import localConf # this is a custom wrapper for ConfigParser. Should be in local dir. 

###########################################################################
# All applet settings go here, and are accessible from everywhere.
###########################################################################
class configuration:
	"An all-encoupasing, application-wide configuration storage location. This is not a permanent file-based storage"
	def __init__(self):
		self.name = "a-Foto"
		self.version = "v1.5.beta7, July 20, 2006"
		self.temasVersion = "20060720"
		self.localeVersion = "20060720"
		self.author = "Trebol-a (info@trebol-a.com)\nDanil (Suslik) Dotsenko (dd@accentsolution.com)"
		self.mode = "single" # other options: "slideshow"
		self.updateInterval = 120000 # 2 minutes. This works only for slideshow mode.
		self.forever = 6000000 # 100 Minutes, this works only in single mode.
		self.updateIntervalPid = None
		self.temasPath = ""
		self.tema = "a-foto" # frame theme
		self.temasList = []
		self.temaPid = None #Used for identifying command putput
		self.maxSize = 180 # limits BOTH! height AND width of FOTO element. Frame can be more than maxSize
		self.maxSizePid = None #Used for identifying command putput
		self.limitByLongerSide = False 
		self.shadowSize = 18
		self.drawFrame = True
		self.drawShadow = True
		self.shadowSizePid = None #Used for identifying command putput
		self.frameParts=["aa","ab","ac","ba","bc","ca","cb","cc"] # used for filenames. "s_" added for shadow, "t_" added for frame
		self.foto = None # see getConfigs(). You cannot defin it here, cause we dont know how to get the widget path yet.
		self.fotoPtr = None # Point to foto object. these point to the actual image pieces in the drawn widget.
		self.sombraPtr=[] # Point to shadow objects object. these point to the actual image pieces in the drawn widget.
		self.estiloPtr=[] # Point to frame objects. these point to the actual image pieces in the drawn widget.
		self.imageFolderPath = None # see getConfigs(). You cannot defin it here, cause we dont know how to get the widget path yet.
		self.fileFilter=re.compile(".+\.(jpg|jpeg|png|gif|bmp)$",re.IGNORECASE)
		self.dirIsLinkFlag = False
		self.widgetWidth = 0
		self.widgetHeight = 0
		self.limitMax = 2000 # this is ARBITRARY number. Needs testing and adjustment.
		self.localePath = None
		self.menu1Items = []
		self.menu1PauseAdded = 0 # this var will be 0 if the Pause menu is NOT created, and will be # of cell in menu1Items in which pointer to the menu lies.
		self.menu2Items = []
		self.cfgObject = localConf.cfgObject() # this one holds all the configs of the app.

###########################################################################
# This is how you make all configs available to you - now a global "variable" with methods.
###########################################################################
appConfig=configuration()

###########################################################################
# This will read the config file for settings
#
def getConfigs(widget):
	global appConfig, _
	
	###########################################################################
	# This is a little peice of Magic!
	#   we determine if we run from *.skz file, and if true, extract it and use new extracted path.
	###########################################################################
	if is_zipfile(karamba.getThemePath(widget)):
		# Note! It is important to understand this section for SKIN AUTHORS and TRANSLATORS!!!
		# Before extracting everything, we will check the config file 
		# YOUR UPDATED SKINS / TRANSLATIONS WILL NOT BE EXTRACTED
		# unless the variables in this script above are updated to higher value.
		homepath = os.environ['HOME']+'/.superkaramba/afoto/'
		if os.path.exists(homepath) == False:
			os.makedirs(homepath)
		toExtract = []
		if appConfig.cfgObject.load(homepath+'afoto.ini', True): # 1 if file was read, 0 if there was no file
			if appConfig.temasVersion > appConfig.cfgObject.get('Global','temasVersion'):
				toExtract.append('temas/*')
				appConfig.cfgObject.set('Global','temasVersion',appConfig.temasVersion)
				appConfig.cfgObject.delayed_action("save")
			if appConfig.localeVersion > appConfig.cfgObject.get('Global','localeVersion'):
				toExtract.append('locale/*')
				appConfig.cfgObject.set('Global','localeVersion',appConfig.localeVersion)
				appConfig.cfgObject.delayed_action("save")
		else: # this means afoto.ini file was not found or contains nothing usefull => completely new install
			toExtract.append('afoto.ini')
			toExtract.append('temas/*')
			toExtract.append('locale/*')
			appConfig.cfgObject.delayed_action("load", homepath+'afoto.ini')
		# now, we know what to extract
		if len(toExtract):
			myCommand = ['unzip', '-o', karamba.getThemePath(widget)]
			myCommand.extend(toExtract)
			myCommand.append('-d')
			myCommand.append(homepath)
			os.spawnvp(os.P_WAIT, 'unzip', myCommand) # this sommand holds the progress until extracting is done.
			appConfig.cfgObject.delayed_action()
		# appConfig.cfgObject.fileName = homepath+'afoto.ini'  # this is not needed, set automatically when initialized
		appConfig.temasPath = homepath+"temas/"
		appConfig.localePath = homepath+"locale/"
	else:	
		# this option uses the folder you run afoto from and sets that as the path for all items
		# NOTE! even config file is localised to the current folder!
		# This behavior is beneficial for troubleshooting and testing, as it will not mess up the "working" settings in ~/.superkaramba/afoto
		appConfig.temasPath=karamba.getThemePath(widget)+"temas/"
		appConfig.localePath=karamba.getThemePath(widget)+"locale/"
		appConfig.cfgObject.load(karamba.getThemePath(widget)+'afoto.ini', True)
		
	###########################################################################
	# This activates gettext-based translation services
	#   from now on, use _('text to translate') instead of 'text to translate'
	###########################################################################	
	lang = []
	lang.append(karamba.language(widget))
	if  lang[0] == None: # karamba.language() function doesn't work in some SuperKaramba versions
		tempOut = commands.getoutput('more ~/.kde/share/config/kdeglobals | grep Language')
		lang = re.split(':',tempOut[9:])
	languageFile=None
	i = 0
	while i < lang.__len__() and languageFile==None:
		# OK, we will try to be nice and compile nonexisting or stale .mo's
		# This should be useful for translators - no need to compile .mo's, just translate the .po and rerun afoto.
		if os.path.exists(appConfig.localePath+lang[i]+".po"):
			if os.path.exists(appConfig.localePath+lang[i]+".mo") == False:
				msgfmtPath = re.compile('/.*msgfmt$').match(commands.getoutput('which msgfmt'))
				if msgfmtPath:
					myCommand = "msgfmt "+appConfig.localePath+lang[i]+".po -o "+appConfig.localePath+lang[i]+".mo"
					commands.getoutput(myCommand)
			languageFile=appConfig.localePath+lang[i]+".mo"
		i = i + 1	
	# thx to Matthew (dmbkiwi@yahoo.com) for shoing the right way of doing this.
	# modified excerpt from LiquidWeather sources
	if(languageFile == None):
		_ = lambda(x): x
	else:
		# s = karamba.readThemeFile(widget, languageFile) # this function does not wotk on fully-formed URLs
		if os.path.exists(languageFile):
			filePointer = open(languageFile,'r')
			fileContents = filePointer.read()
			filePointer.close()
		if fileContents.__len__() > 0:
			gt = GNUTranslations(StringIO(fileContents))
			_ = gt.ugettext
		else:
			_ = lambda(x): x
	# end of excerpt
	
	###########################################################################
	# Creates empty images for shadow (sombra) framame (estilo) and photo (foto)
	#   They are filled with real images later. Coordinates are not important
	###########################################################################
	appConfig.fotoPtr=karamba.createImage(widget,0,0,appConfig.temasPath+"null.png")
	#karamba.attachClickArea(widget, appConfig.fotoPtr)
	karamba.attachClickArea(widget, appConfig.fotoPtr)
	appConfig.sombraPtr=[]
	appConfig.estiloPtr=[]
	for i in range(8): # we get [0-7], no 8
		appConfig.sombraPtr.append(karamba.createImage(widget,1,i,appConfig.temasPath+"null.png"))
		appConfig.estiloPtr.append(karamba.createImage(widget,2,i,appConfig.temasPath+"null.png"))	
	
	# Creates a list of folders with temas inside.
	tempList = os.listdir(appConfig.temasPath)
	for i in range(len(tempList)):
		if os.path.isdir(appConfig.temasPath+tempList[i]) == True:
			appConfig.temasList.append(tempList[i])
	
	# loads the source folder of slideshow images into appConfig.imageFolderPath
	lista=karamba.readConfigEntry(widget, "foto")
	appConfig.foto=appConfig.temasPath+"inicio.png" # this will be used if there is no entry or the actual file was removed
	if lista != None:
		if os.path.exists(lista):
			appConfig.foto=lista

	# loads the source folder of slideshow images into appConfig.imageFolderPath
	lista=karamba.readConfigEntry(widget, "imageFolderPath")
	if lista != None:
		if tryNextImage(widget, lista) == False: # if True, tryNextImage automatically sets the appConfig.imageFolderPath AND appConfig.foto
			print "Error: the folder I pulled from config does not have images inside"
	
	lista = karamba.readConfigEntry(widget, "mode")
	if lista != None:
		if (lista == "slideshow") and (appConfig.imageFolderPath != None):
			appConfig.mode = lista
			karamba.changeInterval(widget,appConfig.updateInterval)
	
	# loads foto and frame limits.
	lista = karamba.readConfigEntry(widget, "ancho_user")
	if lista != None:
		appConfig.maxSize = int(lista)

	lista = karamba.readConfigEntry(widget, "sombra_user")
	if lista != None:
		appConfig.shadowSize = int(lista)
	
	lista = karamba.readConfigEntry(widget, "tema_user")
	if lista != None:
		appConfig.tema = lista
		
	lista = karamba.readConfigEntry(widget,"limitByLongerSide")
	if lista == None or lista == "No":
		appConfig.limitByLongerSide = False
	else:
		appConfig.limitByLongerSide = True

#
###########################################################################


###########################################################################
# These just make it easier to send messages through kdialog.

def notificationWindow(message, title="", mode=None):
	"This uses KDE kdialog app and asks for main body message and window title. App name is attached automatically"
	global appConfig
	myCommand = 'kdialog --caption "'+appConfig.name+'" --title "'+title+'" --msgbox "'+message+'"'
	karamba.execute(myCommand)
#
##########################################################

################## Config Menu Creations / Handling ####################
# Config Menu: creation and handling of menu actions.
#


def createConfMenus(widget):
	"Creates menu that you get from right-clicking on the widget. This is part of layout rutine, include in karamba's init."
	global appConfig, _
	
	# this is the old style menu
	karamba.addMenuConfigOption(widget, "about", _("About ")+appConfig.name+" ...")
	karamba.setMenuConfigOption(widget, "about", 0)
	
	# These are alternatives to the traditional superkaramba "Configure Theme" menu. These will work in Unicode.
	appConfig.menu1Items.append(karamba.createMenu(widget))
	appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Open image in viewer") , "viewmag"))
	appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Show image location") , "bookmark_folder"))
	appConfig.menu1Items.append(karamba.addMenuSeparator(widget, appConfig.menu1Items[0]))
	appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Configure")+" "+appConfig.name , "configure"))
	appConfig.menu1Items.append(karamba.addMenuSeparator(widget, appConfig.menu1Items[0]))
	if appConfig.mode != "single":
		appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Pause slideshow") , "player_pause"))
		appConfig.menu1PauseAdded = appConfig.menu1Items.__len__()-1
	else:
		appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Resume slideshow") , "player_play"))
		appConfig.menu1PauseAdded = appConfig.menu1Items.__len__()-1

	# so, 0 = menu, 1-6 = menu items
	appConfig.menu2Items.append(karamba.createMenu(widget))
	appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Choose frame style...") , "frame_image"))
	appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Set shadow size...") , "transform"))
	appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Set maximum photo size...") , "crop"))
	appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Set slideshow interval...") , "history"))
	appConfig.menu2Items.append(karamba.addMenuSeparator(widget, appConfig.menu2Items[0]))
	appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Limit by longer side") , appConfig.temasPath+"null.png"))
	# so, 0 = menu, 1-6 = menu items

# Reading of old-style menu
def menuOptionChanged(widget, key, value):
	"This function is called when right-click Karamba menu is clicked."
	global appConfig, _
	if key=="about":
		notificationWindow(appConfig.name+'\n'+appConfig.version+'\n'+_('Created by')+':\n'+appConfig.author+'\n'+_('For latest version search kde-look.org for ')+appConfig.name, _("About ")+appConfig.name)
		karamba.setMenuConfigOption(widget, "about", 0)

# Reading of new-style menu
def menuItemClicked(widget, menu, id):
	global appConfig, _
	if (menu == appConfig.menu1Items[0]):
		if(id == appConfig.menu1Items[1]): # View in viewer
			karamba.execute('kfmclient exec "'+appConfig.foto+'"')
		elif(id == appConfig.menu1Items[2]): # show location
			karamba.execute('konqueror --select "'+appConfig.foto+'"')
		elif(id == appConfig.menu1Items[4]): # Configure Menu
			karamba.popupMenu(widget, appConfig.menu2Items[0], 5, 5)
		elif(id == appConfig.menu1Items[6]): # Pause slideshow
			if appConfig.mode == "single" and appConfig.imageFolderPath != None:
				if appConfig.menu1PauseAdded != 0:
					karamba.removeMenuItem(widget, appConfig.menu1Items[0], appConfig.menu1Items[appConfig.menu1PauseAdded]) # removes the last item from menu
					appConfig.menu1Items.remove(appConfig.menu1Items[appConfig.menu1PauseAdded])
				appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Pause slideshow") , "player_pause"))
				appConfig.menu1PauseAdded = appConfig.menu1Items.__len__()-1
				appConfig.mode = "slideshow"
				karamba.changeInterval(widget, appConfig.updateInterval)
			elif appConfig.mode == "slideshow" and appConfig.foto != None:
				if appConfig.menu1PauseAdded != 0:
					karamba.removeMenuItem(widget, appConfig.menu1Items[0], appConfig.menu1Items[appConfig.menu1PauseAdded]) # removes the last item from menu
					appConfig.menu1Items.remove(appConfig.menu1Items[appConfig.menu1PauseAdded])
				appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Resume slideshow") , "player_play"))
				appConfig.menu1PauseAdded = appConfig.menu1Items.__len__()-1
				appConfig.mode = "single"
				karamba.changeInterval(widget, appConfig.forever)
	elif (menu == appConfig.menu2Items[0]):
		if(id == appConfig.menu2Items[1]): # frame
			ventana = ["kdialog", "--caption", appConfig.name, "--title", _("Configure"), "--combobox", _("Select new frame style")]
			appConfig.temaPid = karamba.executeInteractive(widget, ventana+appConfig.temasList)
		elif(id == appConfig.menu2Items[2]): # shadow
			ventana = ["kdialog",  "--caption", appConfig.name, "--title", _("Configure"), "--inputbox", _("Set the width of shadows (pixels)"),str(appConfig.shadowSize)]
			appConfig.shadowSizePid = karamba.executeInteractive(widget, ventana)
		elif(id == appConfig.menu2Items[3]): # size
			ventana = ["kdialog", "--caption", appConfig.name, "--title", _("Configure"), "--inputbox", _("Set the maximum size for your picture (pixels)"),str(appConfig.maxSize)]
			appConfig.maxSizePid = karamba.executeInteractive(widget, ventana)
		elif(id == appConfig.menu2Items[4]): # interval
			ventana = ["kdialog", "--caption", appConfig.name, "--title", _("Configure"), "--inputbox", _("Set the refresh rate (minutes)"), str(int(appConfig.updateInterval/60000))]
			appConfig.updateIntervalPid = karamba.executeInteractive(widget, ventana)
		elif(id == appConfig.menu2Items[appConfig.menu2Items.__len__()-1]): # limit by longer
			if karamba.readConfigEntry(widget,"limitByLongerSide") == "No" or karamba.readConfigEntry(widget,"limitByLongerSide") == None:
				appConfig.limitByLongerSide = True
				karamba.writeConfigEntry(widget,"limitByLongerSide","Yes")
				karamba.removeMenuItem(widget, appConfig.menu2Items[0], appConfig.menu2Items[appConfig.menu2Items.__len__()-1]) # removes the last item from menu
				appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Limit by longer side") , "apply"))
			else:
				appConfig.limitByLongerSide = False
				karamba.writeConfigEntry(widget,"limitByLongerSide","No")
				karamba.removeMenuItem(widget, appConfig.menu2Items[0], appConfig.menu2Items[appConfig.menu2Items.__len__()-1]) # removes the last item from menu
				appConfig.menu2Items.append(karamba.addMenuItem(widget, appConfig.menu2Items[0], _("Limit by longer side") , appConfig.temasPath+"null.png"))
			redrawObjects(widget)

#This gets called when a command you have executed with executeInteractive() outputs something
#to stdout.  This way you can get the output of for example kdialog without freezing up the widget
#waiting for kdialog to end.
#  widget = reference to your theme
#  pid = process number of the program outputting (use this if you execute more than out process)
#  output = the text the program outputted to stdout
def commandOutput(widget, pid, output):
	global appConfig
	if pid == appConfig.maxSizePid and output != "\n":
		appConfig.maxSize = int(output.replace('\n',''))
		redrawObjects(widget)
		karamba.writeConfigEntry(widget, "ancho_user", str(appConfig.maxSize))
	elif pid == appConfig.shadowSizePid and output != "\n":
		appConfig.shadowSize = int(output.replace('\n',''))
		loadTema(widget)
		redrawObjects(widget)
		karamba.writeConfigEntry(widget, "sombra_user", str(appConfig.shadowSize))
	elif pid == appConfig.updateIntervalPid and output != "\n":
		appConfig.updateInterval = int(output.replace('\n',''))*60000
		karamba.changeInterval(widget, appConfig.updateInterval)
	elif pid == appConfig.temaPid and output != "\n":
		appConfig.tema = output.replace('\n','')
		loadTema(widget)
		redrawObjects(widget)
		karamba.writeConfigEntry(widget, "tema_user", appConfig.tema)
#
########################################################################

################## NEXT IMAGE ####################
#  This function selects a random image path from the list in appConfig.imageFolderPath
#  This function is only called in "slideshow" mode (appConfig.mode) on updateWidget()
#  If appConfig.imageFolderPath is not populated, the function doesn't change anything.
def tryNextImage(widget, customPath=None):
	global appConfig, _
	if customPath != None:
		testPath = customPath
	else:
		testPath = appConfig.imageFolderPath
	lista = []
	for root, dirs, files in os.walk(testPath):
		for testDir in dirs:
			if os.path.islink(os.path.join(root, testDir))== True:
				appConfig.dirIsLinkFlag = True
		for name in files:
			if appConfig.fileFilter.search(name) is not None:
				lista.append(os.path.join(root, name))
	if lista.__len__() > 0:
#		limit = 2000  -> Move to appConfig
		if lista.__len__() > appConfig.limitMax:
			notificationWindow(_("The folder you chose contains more than %s images.\nReading this folder at each refresh may be very painful for the system. Please reorganize your sources.") % str(appConfig.limitMax),_("Error"))
			return False # Error! Nothing is changed.
		else:
			if customPath != None:
				appConfig.imageFolderPath = customPath
			appConfig.foto = lista[random.randint(0,lista.__len__()-1)]
			karamba.writeConfigEntry(widget,"foto", appConfig.foto)
			return True
	else:
		return False # Error! Nothing is changed.
#
##################################################

################## LOAD TEMA ####################
#  This function only loads the frame pieces.
#  This is done to separate (and not to waste cycles / harddrive time on) loading frame pieces every time a foto in slide show changes
#  This function need to have appConfig.tema already set to NEW theme.
#  This function also SETS "do not draw" flags to frame / shadow, when needed.
def loadTema(widget):
	global appConfig
	lista = glob.glob(appConfig.temasPath+appConfig.tema+"/t_*.png")
	if len(lista) == 8:
		appConfig.drawFrame = True
		for i in range(8):
			karamba.setImagePath(widget, appConfig.estiloPtr[i], appConfig.temasPath+appConfig.tema+"/t_"+appConfig.frameParts[i]+".png")
	else:
		appConfig.drawFrame = False
		for i in range(8):
			karamba.setImagePath(widget, appConfig.estiloPtr[i], appConfig.temasPath+"null.png")

	lista = glob.glob(appConfig.temasPath+appConfig.tema+"/s_*.png")
	if appConfig.shadowSize>0 and len(lista)==8:
		appConfig.drawShadow = True
		for i in range(8):
			karamba.setImagePath(widget, appConfig.sombraPtr[i], appConfig.temasPath+appConfig.tema+"/s_"+appConfig.frameParts[i]+".png")
	else:
		appConfig.drawShadow = False
		for i in range(8):
			karamba.setImagePath(widget, appConfig.sombraPtr[i], appConfig.temasPath+"null.png")
#
####################################################


################## CHANGE THE FOTO AND FRAME ####################
#  This function does NOT load the frame pieces or tests for their presence.
#  all it does is: changes foto, resizes it, and all ather EXISTING elements.
#  This function reads appConfig.foto var for the location of the foto.
#
def redrawObjects(widget):
	global appConfig, _
	
	########################################################################
	# 1st step of smart relocation routine - getting the "center" stored
	#	need to check if separate frame drowing will not brake this.
	#  -0.25 is there to the move the rounding bias towards higher numbers
	########################################################################	
	
	widgetX, widgetY = karamba.getWidgetPosition(widget)
	widgetX = widgetX + int(round((appConfig.widgetWidth/2)-0.25))
	widgetY = widgetY + int(round((appConfig.widgetHeight/2)-0.25))
		
	# Now we have a center coordinates (relative to the screen) for the applet

	########################################################################
	# Loading image
	########################################################################	

	karamba.setImagePath(widget, appConfig.fotoPtr, appConfig.foto)
	
	########################################################################
	# Determine sizes of everything and resize images.
	########################################################################	
	
	# NOTE!!! VERY IMPORTANT!
	# the function bellow will work ONLY when "from __future__ import division" is on top of file.
	# 
	# RESIZING FOTO
	fotoWidth,fotoHeight = karamba.getImageSize(widget,appConfig.fotoPtr)
	
	# EXIF orientation option detection and image rotation
	if re.compile(".+\.(jpg|jpeg)$",re.IGNORECASE).search(appConfig.foto):
		orientationFlag = commands.getoutput('identify -format "orientation=%[EXIF:Orientation]" "'+appConfig.foto+'"')
		orientFilter = re.compile('(?<=orientation=)[68]{1}(?=\s*$)')
		if orientFilter.search(orientationFlag):
			orientationFlag = int(orientFilter.search(orientationFlag).group(0))
			rotationAngle = (7-orientationFlag)*90 # 6 = 90 degrees, 8 = -90
			karamba.rotateImage(widget, appConfig.fotoPtr, rotationAngle)
			fotoWidth, fotoHeight = fotoHeight, fotoWidth # switching image dimentions for correct frame drawing.
	# this is not used anywhere yet, but will be needed for translations.
	menuoption = _("EXIF-based auto-rotation")
	
	if appConfig.limitByLongerSide==False: # this means, if picture is 1024x768 and maxSize = 180 > size will be 240x180
		if (fotoHeight/fotoWidth) > 1: # it is >1 if image is Tall.
			if fotoWidth > appConfig.maxSize: # than we need to resize
				fotoHeight =  int((fotoHeight * appConfig.maxSize) / fotoWidth)
				fotoWidth = appConfig.maxSize
				karamba.resizeImageSmooth(widget, appConfig.fotoPtr, fotoWidth, fotoHeight)
		else:
			if fotoHeight > appConfig.maxSize: # than we need to resize
				fotoWidth =  int((fotoWidth * appConfig.maxSize) / fotoHeight)
				fotoHeight = appConfig.maxSize
				karamba.resizeImageSmooth(widget, appConfig.fotoPtr, fotoWidth, fotoHeight)
	else: # this means, if picture is 1024x768 and maxSize = 180 > size will be 180x135
		if (fotoWidth/fotoHeight) > 1: # it is >1 if image is wide.
			if fotoWidth > appConfig.maxSize: # than we need to resize
				fotoHeight =  int((fotoHeight * appConfig.maxSize) / fotoWidth)
				fotoWidth = appConfig.maxSize
				karamba.resizeImageSmooth(widget, appConfig.fotoPtr, fotoWidth, fotoHeight)
		else:
			if fotoHeight > appConfig.maxSize: # than we need to resize
				fotoWidth =  int((fotoWidth * appConfig.maxSize) / fotoHeight)
				fotoHeight = appConfig.maxSize
				karamba.resizeImageSmooth(widget, appConfig.fotoPtr, fotoWidth, fotoHeight)
	widgetWidth = fotoWidth
	widgetHeight = fotoHeight
	
	# Now we have "tweaked" fotoWidth and fotoHeight and can use them for other things.
	
	# RESIZING FRAME PIECES
	width0, height0, width7, height7 = 0,0,0,0 # we need this for foto positioning later if the "drawFrame" is false
	if appConfig.drawFrame == True:
		# we will use the corner pieces as guides for all other sizes.
		# (we need 2 corners because one will not work for "non-square" frames like "a-foto")
		# piece 0
		width0,height0 = karamba.getImageSize(widget,appConfig.estiloPtr[0]) # upper left corner piece
		# and piece 7
		width7,height7 = karamba.getImageSize(widget,appConfig.estiloPtr[7]) # lower right corner piece
		# piece 2 is unchanged
		# piece 5 is unchanged
		# we are olny changing the long frame pieces
		karamba.resizeImageSmooth(widget, appConfig.estiloPtr[1], fotoWidth, height0)
		karamba.resizeImageSmooth(widget, appConfig.estiloPtr[3], width0, fotoHeight)
		karamba.resizeImageSmooth(widget, appConfig.estiloPtr[4], width7, fotoHeight)
		karamba.resizeImageSmooth(widget, appConfig.estiloPtr[6], fotoWidth, height7)
		widgetWidth = widgetWidth+width0+width7
		widgetHeight = widgetHeight+height0+height7
	
	# RESIZING SHADOW PIECES
	if appConfig.drawShadow == True:
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[0], appConfig.shadowSize, appConfig.shadowSize)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[2], appConfig.shadowSize, appConfig.shadowSize)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[5], appConfig.shadowSize, appConfig.shadowSize)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[7], appConfig.shadowSize, appConfig.shadowSize)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[1], widgetWidth, appConfig.shadowSize)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[3], appConfig.shadowSize, widgetHeight)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[4], appConfig.shadowSize, widgetHeight)
		karamba.resizeImageSmooth(widget, appConfig.sombraPtr[6], widgetWidth, appConfig.shadowSize)
		widgetWidth = widgetWidth+appConfig.shadowSize*2
		widgetHeight = widgetHeight+appConfig.shadowSize*2
		
	# RESIZING THE WIDGET
	karamba.resizeWidget(widget, widgetWidth, widgetHeight)

	########################################################################
	# MOVING ALL THE PIECES
	########################################################################	
	
	# we need this when tema contains NO files for shadow.
	if appConfig.drawShadow == False:
		shadowSize = 0
	else:
		shadowSize = appConfig.shadowSize
	
	# MOVING FOTO
	karamba.moveImage(widget,appConfig.fotoPtr, width0+shadowSize, height0+shadowSize)
	# it has to be here because moving resets Tips
	karamba.addImageTooltip(widget, appConfig.fotoPtr, _("- Drop image file or folder here.\n- (Double-)Click for options and settings."))
	
	# MOVING FRAME PIECES
	if appConfig.drawFrame == True:
		karamba.moveImage(widget,appConfig.estiloPtr[0], 0+shadowSize, 0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[1], width0+shadowSize, 0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[2], fotoWidth+width0+shadowSize, 0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[3], 0+shadowSize, height0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[4], fotoWidth+width0+shadowSize, height0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[5], 0+shadowSize, fotoHeight+height0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[6], width0+shadowSize, fotoHeight+height0+shadowSize)
		karamba.moveImage(widget,appConfig.estiloPtr[7], fotoWidth+width0+shadowSize, fotoHeight+height0+shadowSize)
	
	# MOVING SHADOW PIECES
	if appConfig.drawShadow == True:
		karamba.moveImage(widget,appConfig.sombraPtr[0], 0, 0)
		karamba.moveImage(widget,appConfig.sombraPtr[1], shadowSize, 0)
		karamba.moveImage(widget,appConfig.sombraPtr[2], width7+fotoWidth+width0+shadowSize, 0)
		karamba.moveImage(widget,appConfig.sombraPtr[3], 0, shadowSize)
		karamba.moveImage(widget,appConfig.sombraPtr[4], width7+fotoWidth+width0+shadowSize, shadowSize)
		karamba.moveImage(widget,appConfig.sombraPtr[5], 0, height7+fotoHeight+height0+shadowSize)
		karamba.moveImage(widget,appConfig.sombraPtr[6], shadowSize, height7+fotoHeight+height0+shadowSize)
		karamba.moveImage(widget,appConfig.sombraPtr[7], width7+fotoWidth+width0+shadowSize, height7+fotoHeight+height0+shadowSize)	
	
	########################################################################
	# 2nd step of smart relocation routine - getting new "center" recalculated and applied
	#	need to check if separate frame drowing will not brake this.
	########################################################################	
	
	if appConfig.widgetWidth != 0: # it will be 0 on 1st run
		widgetX = widgetX - int(round((widgetWidth/2)-0.25))
		widgetY = widgetY - int(round((widgetHeight/2)-0.25))
		karamba.moveWidget(widget, widgetX, widgetY)
	
	appConfig.widgetWidth = widgetWidth
	appConfig.widgetHeight = widgetHeight
	
	# finally, redraw
	karamba.redrawWidget(widget)

##################################################################
# KARAMBA's built-in functions
##################################################################

#this is called when you widget is initialized
def initWidget(widget):
	global appConfig
	# if isThisFirstTime(widget)==False:
	getConfigs(widget)
	# putOldLocation(widget) # this puts the applet at its recorded location.
	createConfMenus(widget) # this creates the config menus (right click)
	loadTema(widget)
	loadImg = karamba.getThemeImage(widget, "loading")
	karamba.deleteImage(widget,loadImg)
	redrawObjects(widget)
	karamba.acceptDrops(widget)
	#karamba.attachClickArea(widget,appConfig.name,"kfmclient exec \""+appConfig.foto+"\"","konqueror --select \""+appConfig.foto+"\"")
		
#this is called everytime your widget is updated
#the update inverval is specified in the .theme file
def widgetUpdated(widget):
	global appConfig
	if appConfig.mode=="slideshow":
		tryNextImage(widget)
		redrawObjects(widget)

def itemDropped(widget, dropText, x=None, y=None):
	# This is very important
	# Type of the dropped object determines the mode of operation.
	# Need to add error handling to it.
	global appConfig, _
	dropText = dropText.replace('file://','')
	if os.path.isfile(dropText):
		if appConfig.fileFilter.search(dropText) != None:
			appConfig.foto = dropText
			karamba.writeConfigEntry(widget,"foto", appConfig.foto) # in slideshow mode, image saved to conf in tryNextImage()
			karamba.writeConfigEntry(widget,"mode", appConfig.mode)
			redrawObjects(widget)
			if appConfig.menu1PauseAdded != 0:
				karamba.removeMenuItem(widget, appConfig.menu1Items[0], appConfig.menu1Items[appConfig.menu1PauseAdded]) # removes the last item from menu
				appConfig.menu1Items.remove(appConfig.menu1Items[appConfig.menu1PauseAdded])
				appConfig.menu1PauseAdded = 0
			appConfig.mode == "single"
			karamba.changeInterval(widget, appConfig.forever)
	elif os.path.isdir(dropText):
		if tryNextImage(widget, dropText) == True: # NO errors in choosing a picture
			if appConfig.dirIsLinkFlag == True:
				notificationWindow(_("At least one folder in the dropped source is a symbolic link.\nSymbolic links of directories are NOT scanned for pictures. This is done to avoid Infinite Loop issues.\nSymbolic links to individual picture files are acceptable.\nPlease reorganize your sources."),_("Error"))
				appConfig.dirIsLinkFlag == False
			redrawObjects(widget)
			karamba.writeConfigEntry(widget,"imageFolderPath", appConfig.imageFolderPath)
			if appConfig.menu1PauseAdded == 0:
				appConfig.menu1Items.append(karamba.addMenuItem(widget, appConfig.menu1Items[0], _("Pause slideshow") , "player_pause"))
				appConfig.menu1PauseAdded = appConfig.menu1Items.__len__()-1
			appConfig.mode = "slideshow"
			karamba.writeConfigEntry(widget,"mode", appConfig.mode)
			karamba.changeInterval(widget, appConfig.updateInterval)

#This gets called everytime our widget is clicked.
#Notes:
#  widget = reference to our widget
#  x = x position (relative to our widget)
#  y = y position (relative to our widget)
#  botton = button clicked:
#                    1 = Left Mouse Button
#                    2 = Middle Mouse Button
#                    3 = Right Mouse Button, but this will never happen
#                        because the right mouse button brings up the
#                        Karamba menu.
#                    4,5 = Scroll wheel up and down
def widgetClicked(widget, x, y, button):
	#btnPressed(widget, x, y, button)
	#pass
	global appConfig
	if(button == 1):
		karamba.popupMenu(widget, appConfig.menu1Items[0], 10, 10)
	elif(button == 2):
		karamba.popupMenu(widget, appConfig.menu2Items[0], 5, 5)

#This gets called everytime mouse is moved over our widget.
#Notes
#  widget = reference to our widget
#  x = x position (relative to our widget)
#  y = y position (relative to our widget)
#  botton = button being held:
#                    0 = No Mouse Button
#                    1 = Left Mouse Button
#                    2 = Middle Mouse Button
#                    3 = Right Mouse Button, but this will never happen
#                        because the right mouse button brings up the
#                        Karamba menu.
def widgetMouseMoved(widget, x, y, button):
    #Warning:  Don't do anything too intensive here
    #You don't want to run some complex piece of code everytime the mouse moves
    pass

#This gets called when a meter (image, text, etc) is clicked.
# NOTE you must use attachClickArea() to make a meter
# clickable.  
#  widget = reference to your theme
#  meter = the meter clicked
#  botton = button clicked:
#                    1 = Left Mouse Button
#                    2 = Middle Mouse Button
#                    3 = Right Mouse Button, but this will never happen
#                        because the right mouse button brings up the
#                        Karamba menu.
#                    4,5 = Scroll wheel up and down
# "kfmclient exec \""+valor_origen+"\"","konqueror --select \""+valor_origen+"\"")
def meterClicked(widget, meter, button):
	pass

# This will be printed when the widget loads.
print appConfig.name+" version "+appConfig.version+" is loaded"
